package com.handinfo.engine;

import java.io.InputStream;
import javax.microedition.media.Player;
import javax.microedition.media.control.VolumeControl;
import javax.microedition.media.MediaException;

import com.xl.lib.Utils;

import java.io.DataInputStream;
import java.io.ByteArrayInputStream;

/**
 * 音乐类 处理背景音以及音效
 * <p>
 * Title:
 * </p>
 * 
 * <p>
 * Description:
 * </p>
 * 
 * <p>
 * Copyright: Copyright (c) 2009
 * </p>
 * 
 * <p>
 * Company: OBM
 * </p>
 * 
 * @author Xia Mingwei
 * @version 1.0
 */
public class Music
{
	private static Music instance;
	private boolean m_soundOn = false;
	private int m_level = 80;

	private Music()
	{
	}

	public void openMusic()
	{
		m_soundOn = true;
		setLevel(80);
	}

	public void closeMusic()
	{
		m_soundOn = false;
		setLevel(0);
		stopBackground();
	}

	public boolean isSoundOn()
	{
		return m_soundOn;
	}

	public static Music getInstance()
	{
		if (instance == null) {
			instance = new Music();
		}
		return instance;
	}

	private int m_curBackgroundMusicId;
	private BackgroundMusic backgroundMusic;
	private EffectMusic effectMusics[];

	public static final String SOUND_BG_FILE_NAME = "/sound_bg.bin";
	public static final String SOUND_EFFECT_FILE_NAME = "/soundEffect.bin";

	public static final String SOUND_TYPE_MIDI = "audio/midi";
	public static final String SOUND_TYPE_WAV = "audio/x-wav";

	public static final int BG_MUSIC_COVER = 0; // 主界面
	public static final int BG_MUSIC_NEWVILLAGE = 1; // 新手村
	public static final int BG_MUSIC_TOWN_HUMAN = 2; // 人主城
	public static final int BG_MUSIC_TOWN_DEVIL = 3; // 鬼主城
	public static final int BG_MUSIC_TOWN_IMMORTAL_ = 4; // 仙主城
	public static final int BG_MUSIC_FIELD = 5;//野外
	public static final int BG_MUSIC_WAR = 6;//战场

	public void loadBackground(String path, int id)
	{
		m_curBackgroundMusicId = id;
		if (!m_soundOn)
			return;
		if (this.backgroundMusic == null) {
			this.backgroundMusic = new BackgroundMusic(path, id);
			this.backgroundMusic.setLevel(this.m_level);
		}
		if (this.backgroundMusic != null && this.backgroundMusic.id != id) {
			this.backgroundMusic.stop();
			this.backgroundMusic = null;
			this.backgroundMusic = new BackgroundMusic(path, id);
			this.backgroundMusic.setLevel(this.m_level);
		}
	}

	public int getCurBackGroundId()
	{
		return m_curBackgroundMusicId;
	}

	public void setCurBackGroundId(int id)
	{
		m_curBackgroundMusicId = id;
	}

	public static Player loadSound(String fileName, int soundID, String type)
	{
		try {
			DataInputStream dis = new DataInputStream(
//					fileName.getClass()
					Utils
					.getResourceAsStream(fileName));
			int blockNum = dis.readInt();
			int[] soundOffsets = new int[blockNum];
			for (int i = 0; i < blockNum; i++) {
				soundOffsets[i] = dis.readInt();
			}
			for (int i = 0; i < blockNum; i++) {
				int size = soundOffsets[i + 1] - soundOffsets[i];
				if (i < soundID) {
					dis.skip(size);
				}
				else {
					byte[] buffer;
					buffer = new byte[size];
					dis.read(buffer);
					InputStream is = new ByteArrayInputStream(buffer);
					Player soundPlayer = javax.microedition.media.Manager
							.createPlayer(is, type);
					is.close();
					// soundPlayer.realize();
					// soundPlayer.prefetch();
					is = null;
					buffer = null;
					dis.close();
					dis = null;
					return soundPlayer;
				}
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public void loadEffect(String path, int[] id)
	{
		if (!m_soundOn)
			return;
		int len = id.length;
		this.effectMusics = new EffectMusic[len];
		for (int i = 0; i < len; i++) {
			this.effectMusics[i] = new EffectMusic(path, id[i]);
		}
	}

	public void playBackground()
	{
		if (!m_soundOn)
			return;
		if (this.backgroundMusic != null && !this.backgroundMusic.isPlaying()) {
			this.backgroundMusic.play();
		}
	}

	public void pauseBackground()
	{
		if (!m_soundOn)
			return;
		if (this.backgroundMusic != null) {
			this.backgroundMusic.pause();
		}
	}

	public void stopBackground()
	{
		if (this.backgroundMusic != null) {
			this.backgroundMusic.stop();
			this.backgroundMusic = null;
		}
	}

	public BackgroundMusic getBackground()
	{
		return this.backgroundMusic;
	}

	public void playEffect(int index)
	{
		if (!m_soundOn)
			return;
		if (this.effectMusics != null) {
			if (index < 0 || index >= this.effectMusics.length) {
				return;
			}
			this.effectMusics[index].play();
		}
	}

	public int getLevel()
	{
		return m_level;
	}

	public void setLevel(int level)
	{
		m_level = level;
		if (getBackground() != null) {
			getBackground().setLevel(level);
		}
	}

	public void destroy()
	{
		if (this.backgroundMusic != null) {
			this.backgroundMusic.stop();
			this.backgroundMusic = null;
		}
		if (this.effectMusics != null) {
			for (int i = 0; i < this.effectMusics.length; i++) {
				this.effectMusics[i].stop();
				this.effectMusics[i] = null;
			}
			this.effectMusics = null;
		}
	}

	public class BackgroundMusic
	{
		private Player player;
		private VolumeControl control;
		private int level;
		private String file;
		private long startTime;
		private int id;

		public BackgroundMusic(String file, int id)
		{
			try {
				this.file = file;
				this.id = id;

				this.player = loadSound(this.file, this.id, SOUND_TYPE_MIDI);
				this.player.realize();
				this.player.prefetch();
				this.player.setLoopCount(-1);
				this.control = ((VolumeControl) this.player
						.getControl("VolumeControl"));
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}

		public boolean play()
		{
			try {
				if (this.player == null) {
					return false;
				}
				else {
					this.player.start();
					this.startTime = System.currentTimeMillis()
							- (this.player.getMediaTime() / 1000);
					return true;
				}
			}
			catch (Exception e) {
				e.printStackTrace();
				return false;
			}
		}

		public boolean pause()
		{
			try {
				if (this.player == null) {
					return false;
				}
				else {
					this.player.stop();
					return true;
				}
			}
			catch (Exception e) {
				e.printStackTrace();
				return false;
			}

		}

		public boolean stop()
		{
			try {
				if (this.player == null) {
					return false;
				}
				else {
					this.player.stop();
					this.player.deallocate();
					this.player.close();
					this.player = null;
					this.control = null;
					return true;
				}
			}
			catch (Exception e) {
				e.printStackTrace();
				return false;
			}
		}

		public boolean isPlaying()
		{
			if (this.player != null && this.player.getState() == Player.STARTED)
				return true;
			else {
				return false;
			}
		}

		public void setLevel(int level)
		{
			if (this.control == null) {
				return;
			}
			else {
				if (level < 0) {
					this.level = 0;
					if (!this.control.isMuted()) {
						this.control.setMute(true);
					}
					return;
				}
				else {
					if (level > 100) {
						return;
					}
					else {
						this.level = level;
						this.control.setLevel(this.level);
						if (this.control.isMuted()) {
							this.control.setMute(false);
						}
					}
				}
				return;
			}
		}

		public int getLevel()
		{
			return this.level;
		}

		public long getMediaTime()
		{
			if (this.player == null) {
				return 0;
			}
			else {
				if (this.player.getState() == Player.STARTED) {
					return this.player.getMediaTime();
				}
				else {
					return 0;
				}
			}
		}

		public long getDuration()
		{
			if (this.player == null) {
				return 0;
			}
			else {
				return this.player.getDuration() / 1000;
			}
		}

		public boolean setLoop(int loop)
		{
			if (this.player != null) {
				this.player.setLoopCount(loop);
				return true;
			}
			else {
				return false;
			}
		}

		public long getStartTime()
		{
			return this.startTime;
		}

		public long getPlayTime()
		{
			return System.currentTimeMillis() - this.startTime;
		}
	}

	public class EffectMusic
	{
		private Player player;

		public EffectMusic(String file, int id)
		{
			try {
				this.player = loadSound(file, id, SOUND_TYPE_WAV);
				this.player.realize();
				this.player.prefetch();
				this.player.setLoopCount(1);
			}
			catch (Exception ex) {
				ex.printStackTrace();
			}
		}

		public boolean play()
		{
			try {
				if (this.player == null) {
					return false;
				}
				else {
					this.player.start();
				}
			}
			catch (Exception e) {
				e.printStackTrace();
				return false;
			}
			return false;
		}

		public boolean pause()
		{
			return false;
		}

		public boolean stop()
		{
			if (this.player == null) {
				return false;
			}
			else {
				try {
					this.player.stop();
					this.player.deallocate();
					this.player.close();
					this.player = null;
					return true;
				}
				catch (MediaException ex) {
					ex.printStackTrace();
					return false;
				}
			}
		}
	}

}
